package com.yy.tech.inte.service.initializer;

import org.springframework.util.AntPathMatcher;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;

import java.net.URI;
import java.net.URISyntaxException;
import java.util.Map;
import java.util.Optional;

public final class RequestPathUtils {

    private static AntPathMatcher matcher = new AntPathMatcher();
    /***
     * uri must format ,eg:/product/{productCode}-{productVersion}/load/{advert}?test= {kkk}
     * uri variable must be format {XXX}
     * if variable is ${XXX} ,this is  Not necessary
     * @param uri
     * @param uriVariables
     * @return
     */
    public static String build(String uri, Map<String,?> uriVariables){
        if(!StringUtils.isEmpty(uri) &&  null != uriVariables &&!uriVariables.isEmpty()){
            if (uri.indexOf("{")>-1){
                for (Map.Entry<String,?> entry: uriVariables.entrySet()) {
                    String key = entry.getKey();
                    Object value = entry.getValue();
                    if(StringUtils.isEmpty(value)) throw new RuntimeException(key+" for value is empty.");
                    String pattern = "{"+key+"}";
                    uri=uri.replace(pattern,value.toString());
                }
                uri=removeRedundancy(uri);
                if (uri.contains("$")){
                    uri = uri.replace("$","");
                }
            }else if (uri.endsWith("?")){
                for (Map.Entry<String,?> entry: uriVariables.entrySet()) {
                    String key = entry.getKey();
                    Object value = entry.getValue();
                    if(StringUtils.isEmpty(value)) throw new RuntimeException(key+" for value is empty.");
                    StringBuilder sb = new StringBuilder();
                    if (!uri.endsWith("?")){
                        sb.append("&");
                    }
                    sb.append(key+"="+value.toString());
                    uri=uri+sb.toString();
                }
            }else if (uri.endsWith("/")){
                Object var = getFirstVariables(uriVariables);
                if (!ObjectUtils.isEmpty(var)){
                    uri = uri+var.toString();
                }
            }
            if (uri.indexOf("{") >-1 || uri.indexOf("}") >-1 || uri.endsWith("?")){
                throw  new RuntimeException(uri+" some variable not replace.");
            }
        }
        if (uri.endsWith("?")){
            uri = uri.replace("?","");
        }
        return uri;
    }

    private static String removeRedundancy(final String uri) {
        if (!uri.contains("${")) {
            return uri;
        }
        String str = uri;
        if (str.lastIndexOf("${") > 1) {
            String s1 = str.substring(0, str.lastIndexOf("$"));
            if (s1.endsWith("/")) {
                s1 = s1.substring(0, s1.length() - 1);
            }
            final String s2 = str.substring(str.indexOf("}", str.lastIndexOf("${")) + 1);
            str = s1 + s2;
        }
        return removeRedundancy(str);
    }

    private static Object getFirstVariables(Map<String,?> uriVariables){
        if (null != uriVariables && !uriVariables.isEmpty()){
            Optional<?> obj = uriVariables.values().stream().findFirst();
            if (obj.isPresent()){
                return obj.get();
            }
        }
        return null;
    }

    public static String buildPath(String host,String uri){
        return buildPath(host,uri,null);
    }

    public static String buildPath(String host,String uri,Map<String,?> uriVariables){
        StringBuilder builder = new StringBuilder();
        if (!StringUtils.isEmpty(host)){
            if (host.endsWith("/")){
                host=host.substring(0,host.length()-1);
            }
            builder.append(host);
        }
        if (!StringUtils.isEmpty(uri)){
            if (null != uriVariables && !uriVariables.isEmpty()){
                uri = build(uri,uriVariables);
            }
            if (!uri.startsWith("/")){
                builder.append("/");
            }
            builder.append(uri);
        }
        return builder.toString();
    }

    public static boolean match(String path,String pattern){
        return matcher.match(pattern,path);
    }

    public static boolean match(String path,String[] patterns){
        for (String pattern:patterns) {
            if (match(path,pattern)){
                return true;
            }
        }
        return false;
    }

    public static String getHost(String path){
        try {
            URI uri = new URI(path);
            return uri.getHost();
        } catch (URISyntaxException e) {
            e.printStackTrace();
        }
        return path;
    }
}
